import time
import ctypes
import win32api
import win32con


# 定义 Windows API 常量
MOUSEEVENTF_MOVE = 0x0001

MOUSEEVENTF_LEFTDOWN = 0x0002
MOUSEEVENTF_LEFTUP = 0x0004
MOUSEEVENTF_RIGHTDOWN = 0x0008
MOUSEEVENTF_RIGHTUP = 0x0010
MOUSEEVENTF_MIDDLEDOWN = 0x0020
MOUSEEVENTF_MIDDLEUP = 0x0040

MOUSEEVENTF_WHEEL = 0x0800
MOUSEEVENTF_ABSOLUTE = 0x8000


class MouseOperator:
    def __init__(self):
        ctypes.windll.user32.SetProcessDPIAware()
        self.screen_width = ctypes.windll.user32.GetSystemMetrics(0)
        self.screen_height = ctypes.windll.user32.GetSystemMetrics(1)
        self.offset_x = 0
        self.offset_y = 0

    def set_offset(self, offset_x, offset_y):
        self.offset_x = int(offset_x)
        self.offset_y = int(offset_y)

    def hwnd_warp_pos(self, pos):
        # windowsの神奇API
        x = pos[0]
        y = pos[1]
        x += self.offset_x
        y += self.offset_y
        return win32api.MAKELONG(int(x), int(y))

    def hwnd_silent_click(self, hwnd, pos):
        """
        对窗口后台点击
        @args: int, tuple
        """
        if not isinstance(pos, tuple) or len(pos) != 2:
            print('passing slient_click() wrong params.')
            return  # make sure pos is (x, y)
        pos = self.hwnd_warp_pos(pos)

        # PostMessage(HWND hWnd，UINT Msg，WPARAM wParam，LPARAM lParam)
        win32api.PostMessage(hwnd, win32con.WM_LBUTTONDOWN, 0, pos)
        time.sleep(0.1)
        win32api.PostMessage(hwnd, win32con.WM_LBUTTONUP, 0, pos)

    def move_to(self, x, y):
        """将鼠标移动到屏幕上的绝对位置 (x, y)"""
        x += self.offset_x
        y += self.offset_y
        # 转换为 Windows API 需要的坐标 (0-65535)
        normalized_x = int(x * 65535 / self.screen_width)
        normalized_y = int(y * 65535 / self.screen_height)
        ctypes.windll.user32.mouse_event(
            MOUSEEVENTF_ABSOLUTE | MOUSEEVENTF_MOVE,
            normalized_x, normalized_y, 0, 0
        )
    
    def left_click(self, x, y):
        """在指定位置执行左键单击（如果提供坐标则先移动）"""
        self.move_to(x, y)
        time.sleep(0.05)  # 短暂延迟确保移动完成

        ctypes.windll.user32.mouse_event(MOUSEEVENTF_LEFTDOWN, 0, 0, 0, 0)
        time.sleep(0.05)  # 模拟人类点击持续时间
        ctypes.windll.user32.mouse_event(MOUSEEVENTF_LEFTUP, 0, 0, 0, 0)

    def left_drag(self, start_x, start_y, end_x, end_y, duration=0.1):
        """执行左键拖拽操作（从起点拖到终点）"""
        self.move_to(start_x, start_y)
        
        # 按下鼠标左键
        ctypes.windll.user32.mouse_event(MOUSEEVENTF_LEFTDOWN, 0, 0, 0, 0)
        # time.sleep(0.1)
        
        # 平滑移动到终点
        steps = 20
        dx = (end_x - start_x) / steps
        dy = (end_y - start_y) / steps
        for i in range(steps):
            self.move_to(start_x + dx * (i + 1), start_y + dy * (i + 1))
            time.sleep(duration / steps)
        
        # 释放鼠标左键
        ctypes.windll.user32.mouse_event(MOUSEEVENTF_LEFTUP, 0, 0, 0, 0)
